package rhc.spider.engine;

import java.util.Iterator;

import rhc.spider.common.SpiderData;
import rhc.spider.crawler.Crawler;
import rhc.spider.engineExecuter.EngineExecuter;
import rhc.spider.engineExecuter.impl.NormalEngineExecuter;
import rhc.spider.request.Request;
import rhc.spider.request.Response;
import rhc.spider.setting.Setting;
import rhc.spider.spider.Spider;
import rhc.spider.util.AsyncSemaphoreUtil;
import rhc.spider.util.AsyncTaskUtil;

abstract public class BasicEngine implements Engine{

	protected Crawler crawler;
	
	protected EngineExecuter executer;
	
	protected Setting setting;
	
	private Object asyncCountLock=new Object();
	
	private Object runningLock=new Object();
	
	public BasicEngine(Crawler crawler,Setting setting){
		this.crawler=crawler;
		this.setting=setting;
		this.executer=new NormalEngineExecuter(crawler,setting);
		
		AsyncSemaphoreUtil.createSemaphore(runningLock, 1, false);
		AsyncSemaphoreUtil.createSemaphore(asyncCountLock,setting.getInt(Setting.ASYNC_COUNT), false);
	}
	
	@Override
	public Crawler getCrawler(){
		return crawler;
	}
	
	@Override
	public Setting getSetting(){
		return setting;
	}
	
	@Override
	public EngineExecuter getEngineExecuter(){
		return executer;
	}
	
	@Override
	public void open() {
		run();
	}

	@Override
	public void close() {
		// TODO 自动生成的方法存根
		
	}
	
	@Override
	public void addRequest() {
		run();
	}
	
	/**
	 * 开始执行request，
	 */
	private void run(){
		if(AsyncSemaphoreUtil.acquireSemaphore(runningLock, 1, 1)){
			AsyncTaskUtil.asyncTask(new Runnable(){

				@Override
				public void run() {
					try{
						Iterator<Request> iterator=crawler.getSchedule().iterator();
						while(iterator.hasNext()){
							final Request request=iterator.next();
							if(AsyncSemaphoreUtil.acquireSemaphore(asyncCountLock, 1, -1)){
								AsyncTaskUtil.asyncTask(new Runnable(){

									@Override
									public void run() {
										try{
											executer.executeRequest(request);
										}finally{
											AsyncSemaphoreUtil.releaseSemaphore(asyncCountLock, 1);
										}
									}
									
								});
							}
						}
					}finally{
						AsyncSemaphoreUtil.releaseSemaphore(runningLock, 1);
					}
				}
				
			});
			
		}
	}
}
